# -*- coding: utf-8 -*-
# @Time : 2019/8/24 17:58
# @Author : ricky
# @File : main.py
# @Software: vscode
"""主界面"""
import sys
import os
import subprocess
import threading
import zipfile
import datetime
import wx
import wx.adv
import ui
from . import main_frame as frame
from loguru import logger
from constant import constant
from spider import upgradespider
from utils import configini
from utils import path
from core import alterparam
from core import ruoyi
from core import ruoyicloud
from core import ruoyifast
from core import ruoyivue
import platform


class TaskThread(threading.Thread):
    def __init__(self, parent, select_file_path, alter_param: alterparam.AlterParam, rbm_index):
        """
        :param parent:  主线程UI
        """
        super(TaskThread, self).__init__()
        self.parent = parent
        self.select_file_path = select_file_path
        alter_param.context = self
        self.alter_param = alter_param
        self.rbm_index = rbm_index
        self.setDaemon(True)

    def show_operate_log(self, log):
        """
        统一显示日志到控件

        参数:
            self (object): 当前对象
            log (str): 日志内容
        """
        # 这里要在主线程更新UI，否则会报错
        wx.CallAfter(self.parent.receive_call_after, log + '\n')

    def run(self):
        wx.CallAfter(self.parent.task_start)
        self.show_operate_log('正在检测文件...')
        select_dir_path = os.path.dirname(self.select_file_path)
        # 目标目录
        target_dir = os.path.join(
            select_dir_path, datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
        # 记录输出目录
        globals()['output_directory'] = target_dir
        # 解压到指定的文件夹
        with zipfile.ZipFile(self.select_file_path, 'r') as zip_file:
            zip_file.extractall(target_dir)
        self.show_operate_log('输出目录：' + target_dir)
        self.show_operate_log('解压完成，正在修改文件请稍后...')
        # 读取配置文件
        config_dict = configini.Config().get_dict()
        # 读取模板配置文件
        template_config_path = path.resource_path('template_config.ini')
        if not os.path.exists(template_config_path):
            template_config_path = path.resource_path(
                os.path.join('conf', 'template_config.ini'))
        template_dict = configini.Config(template_config_path).get_dict()
        # 实例化核心修改类
        self.alter_param.targetdir = target_dir
        if self.rbm_index == 0:
            ry = ruoyi.RuoYi(self.alter_param, config_dict, template_dict,
                             self.show_operate_log)
        elif self.rbm_index == 1:
            ry = ruoyivue.RuoYiVue(
                self.alter_param, config_dict, template_dict, self.show_operate_log)
        elif self.rbm_index == 2:
            ry = ruoyifast.RuoYiFast(
                self.alter_param, config_dict, template_dict, self.show_operate_log)
        elif self.rbm_index == 3:
            ry = ruoyicloud.RuoYiCloud(
                self.alter_param, config_dict, template_dict, self.show_operate_log)
        try:
            # 开始修改
            ry.start()

        except Exception as error:
            self.show_operate_log('-------------------\n\r')
            self.show_operate_log('修改发生异常：\n{}'.format(error))
            self.show_operate_log('\r----------------------')
            logger.error('修改发生异常：{}', error)
        finally:
            self.parent.task_finally()
            logger.info('修改完成，输出目录：{}', target_dir)
            self.show_operate_log('输出目录：' + target_dir)
            self.show_operate_log('任务结束!')


class Main(frame.MainFrame):
    def __init__(self, parent):
        frame.MainFrame.__init__(self, parent)

        app_name = wx.GetApp().GetAppName()
        if app_name != 'run' and platform.system().lower().startswith('win'):
            icon = wx.Icon(f'{app_name}.exe', wx.BITMAP_TYPE_ICO)
            self.SetIcon(icon)

        self.m_filePicker.GetPickerCtrl().SetLabel('选择文件')
        self.m_filePicker.GetTextCtrl().SetHint('请选择从官网下载下来的“.zip”后缀的压缩文件')

        self.m_text_ctrl_project_dir_name.SetHint('请输入目录名称')
        self.m_text_ctrl_project_name.SetHint('请输入项目名称')
        self.m_text_ctrl_package_name.SetHint('请输入包名')
        self.m_text_ctrl_artifact_id.SetHint('请输入artifactId')
        self.m_text_ctrl_group_id.SetHint('请输入groupId')
        self.m_text_ctrl_site_name.SetHint('请输入站点名称')

        self.m_statusbar.SetFieldsCount(4)  # 状态栏分成4个区域
        # self.m_statusbar.SetStatusWidths([-5,-2]) #区域宽度比列，用负数
        self.m_statusbar.SetStatusText('  软件版本：' + constant.APP_VERSION_STRING,
                                       0)
        self.m_statusbar.SetStatusText(
            '  Python版本：' + constant.PYTHON_VERSION_STRING, 1)
        self.m_statusbar.SetStatusText(
            '  WxPython版本：' + constant.WXPYTHON_VERSION_STRING, 2)
        self.m_statusbar.SetStatusText('  联系作者(RICKY)：QQ11748854', 3)

        self.Centre()

    def task_start(self):
        """
        任务开始
        """
        self.m_text_log.Clear()
        # 禁用按钮
        self.m_btn_start.Disable()
        self.m_btn_clear.Disable()
        self.m_btn_open_output_directory.Disable()

    def task_finally(self):
        """
        任务结束
        """
        self.m_btn_open_output_directory.Enable()
        # 启用按钮
        self.m_btn_start.Enable()
        self.m_btn_clear.Enable()

    def show_message(self, message):
        """
        统一显示对话框

        参数:
                message (str): 对话框内容
        """
        wx.MessageDialog(self, message, '操作提醒', wx.OK).ShowModal()

    def receive_call_after(self, message):
        """
        接收子线程传递消息，刷新UI线程

        参数:
            self (object): 当前对象
            message (str): 日志内容
        """
        self.m_text_log.AppendText(message)
        self.m_text_log.ShowPosition(self.m_text_log.GetLastPosition())

    def upgrade_call_after(self, is_new_version, show_no_new_version_tip, message=None):
        """
        接收更新程序线程传递消息，弹窗提示框

        参数:
            self (object): 当前对象
            is_new_version (bool): 是否是新版本
            show_no_new_version_tip (bool): 是否显示提示
            message (str): 消息
        """
        logger.info('\n%s' % message)
        if is_new_version:
            dlg = wx.GenericMessageDialog(
                self, message, '版本更新提醒', wx.OK | wx.CANCEL)
            dlg.SetOKCancelLabels('前往升级', '忽略更新')
            if dlg.ShowModal() == wx.ID_OK:
                wx.LaunchDefaultBrowser(
                    'https://gitee.com/lpf_project/RuoYi-MT/releases')
            dlg.Destroy()
        else:
            if show_no_new_version_tip:
                wx.MessageDialog(self, message, '版本更新提醒', wx.OK).ShowModal()

    def check_input(self):
        """
        校验输入框

        参数:
            self (object): 当前对象
        Return:
            提示消息,校验通过返回''
        """
        message = ''
        # 验证输入框是否有值
        if len(self.m_text_ctrl_project_dir_name.GetValue()) == 0:
            message = '请填写目录名称'
        if len(self.m_text_ctrl_project_name.GetValue()) == 0:
            message = '请填写项目名'
        if len(self.m_text_ctrl_package_name.GetValue()) == 0:
            message = '请填写包名'
        if len(self.m_text_ctrl_artifact_id.GetValue()) == 0:
            message = '请填写artifactId'
        if len(self.m_text_ctrl_group_id.GetValue()) == 0:
            message = '请填写groupId'
        if len(self.m_text_ctrl_site_name.GetValue()) == 0:
            message = '请填写站点名称'
        return message

    # 实现开始执行按钮的事件
    def OnClickEventStart(self, event):
        select_file_path = self.m_filePicker.GetPath()
        if len(select_file_path) == 0:
            self.show_message('请选择文件')
            return
        if select_file_path.endswith('.zip') is False:
            self.show_message('请选择标准的.zip文件')
            return
        if os.path.exists(select_file_path) is False:
            self.show_message('请选择有效的.zip文件')
            return
        message = self.check_input()
        if len(message) != 0:
            self.show_message(message)
            return
        dlg = wx.MessageDialog(None, '确认开始执行吗？', '操作提醒', wx.YES_NO)
        if dlg.ShowModal() == wx.ID_YES:
            dlg.Destroy()
            # 构造参数
            params = alterparam.AlterParam()
            params.sitename = self.m_text_ctrl_site_name.GetValue()
            params.projectdirname = self.m_text_ctrl_project_dir_name.GetValue()
            params.packagename = self.m_text_ctrl_package_name.GetValue()
            params.projectname = self.m_text_ctrl_project_name.GetValue()
            params.artifactid = self.m_text_ctrl_artifact_id.GetValue()
            params.groupid = self.m_text_ctrl_group_id.GetValue()
            rbm_index = self.m_radio_box_mode.GetSelection()
            t = TaskThread(self, select_file_path, params, rbm_index)
            t.start()

    # 实现退出菜单事件
    def OnMenuClickEventExit(self, event):
        dlg = wx.MessageDialog(self, '确认退出程序吗？', '退出提醒', wx.YES_NO)
        dlg.SetYesNoLabels('退出', '取消')
        if dlg.ShowModal() == wx.ID_YES:
            self.Destroy()
        dlg.Destroy()

    def OnMenuClickEventConfig(self, event):
        dlg = ui.config.config.Config(self)
        dlg.ShowModal()
        dlg.Destroy()

    def OnMenuClickEventTemplateConfig(self, event):
        dlg = ui.config.templateConfig.TemplateConfig(self)
        dlg.ShowModal()
        dlg.Destroy()

    # 实现清空按钮的事件
    def OnClickEventClear(self, event):
        self.m_filePicker.SetPath('')
        self.m_text_ctrl_project_dir_name.SetValue('')
        self.m_text_ctrl_project_name.SetValue('')
        self.m_text_ctrl_package_name.SetValue('')
        self.m_text_ctrl_artifact_id.SetValue('')
        self.m_text_ctrl_group_id.SetValue('')
        self.m_text_ctrl_site_name.SetValue('')
        self.m_text_log.SetValue('')
        self.m_btn_open_output_directory.Disable()
        self.m_radio_box_mode.SetSelection(0)

    # 实现打开输出目录按钮的事件
    def OnClickEventOpenOutputDirectory(self, event):
        directory = globals()['output_directory']
        try:
            os.startfile(directory)
        except:
            subprocess.Popen(['open', directory])

    # 实现打赏作者事件
    def OnMenuClickEventReward(self, event):
        dlg = ui.reward.Reward(self)
        dlg.ShowModal()
        dlg.Destroy()

    # 实现druid秘钥生成事件
    def OnMenuClickEventDruidEncrypt(self, event):
        dlg = ui.druidencrypt.DruidEncrypt(self)
        dlg.ShowModal()
        dlg.Destroy()

    # 实现批量删除文件事件
    def OnMenuClickEventDeleteFile(self, event):
        dlg = ui.filedel.FileDel(self)
        dlg.ShowModal()
        dlg.Destroy()

    # 实现关于事件
    def OnAbout(self, event):
        dlg = ui.about.About(self)
        dlg.ShowModal()
        dlg.Destroy()

    # 实现检测更新事件
    def OnUpgrade(self, event):
        t = upgradespider.UpgradeThread(self, True)
        t.start()

    # 实现使用指南事件
    def OnManual(self, event):
        dlg = ui.manual.Manual(self)
        dlg.ShowModal()
        dlg.Destroy()

    # 实现打开程序目录事件
    def OnOpenAppDir(self, event):
        dir = path.resource_path('')
        try:
            os.startfile(dir)
        except:
            subprocess.Popen(['open', dir])
